/**
 * MongoDB 数据库连接和操作服务
 * 用于管理医院数字孪生系统的数据
 */

import { MongoClient, Db, Collection } from 'mongodb'

// 数据库配置
const MONGODB_URI = 'mongodb+srv://1191665779:20020219aa@zn.apmsejq.mongodb.net/'
const DB_NAME = 'medical_digital_twin'

// 数据类型定义
export interface HospitalData {
  _id?: string
  id: string
  name: string
  level: string
  address: string
  phone: string
  totalBeds: number
  dailyCapacity: number
  founded: string
  staff: number
  center: [number, number] // 经纬度中心点
  bounds: {
    north: number
    south: number
    east: number
    west: number
  }
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface DepartmentData {
  _id?: string
  id: string
  hospitalId: string
  name: string
  type: 'outpatient' | 'inpatient' | 'emergency' | 'surgery' | 'laboratory' | 'radiology' | 'pharmacy' | 'administration'
  floor: string
  capacity: number
  director: string
  phone: string
  position: [number, number] // 经纬度
  status: 'active' | 'inactive' | 'maintenance'
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface EquipmentData {
  _id?: string
  id: string
  hospitalId: string
  departmentId?: string
  name: string
  type: 'ct' | 'mri' | 'xray' | 'ultrasound' | 'bed' | 'wheelchair' | 'defibrillator' | 'ventilator' | 'toilet' | 'elevator' | 'entrance' | 'exit'
  location: string
  status: 'running' | 'idle' | 'maintenance' | 'busy'
  uptime: number
  currentUtilization: number
  maintenance: {
    lastDate: Date
    nextDate: Date
    status: 'scheduled' | 'overdue'
  }
  specifications: {
    manufacturer: string
    model: string
    year: number
  }
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface AlertData {
  _id?: string
  id: string
  hospitalId: string
  type: 'crowding' | 'equipment' | 'environment' | 'supply' | 'traffic'
  severity: 'low' | 'medium' | 'high' | 'critical'
  title: string
  location: string
  description: string
  timestamp: Date
  status: 'active' | 'in_progress' | 'pending' | 'monitoring' | 'resolved'
  assignee: string
  estimatedResolution: string
  impact: string
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface PatientFlowData {
  _id?: string
  id: string
  hospitalId: string
  hour: number
  time: string
  patients: number
  emergency: number
  outpatient: number
  inpatient: number
  date: Date
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface KPIData {
  _id?: string
  id: string
  hospitalId: string
  metric: 'bedUtilization' | 'patientFlow' | 'equipmentEfficiency' | 'patientSatisfaction' | 'emergencyResponse' | 'averageWaitTime'
  value: number
  target: number
  trend: number
  status: 'excellent' | 'good' | 'warning' | 'critical'
  timestamp: Date
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

export interface POIData {
  _id?: string
  id: string
  hospitalId: string
  floorId?: string
  name: string
  type: 'department' | 'equipment' | 'entrance' | 'elevator' | 'stairs' | 'toilet' | 'emergency' | 'cafe' | 'pharmacy' | 'lab' | 'imaging'
  position: [number, number] // 经纬度
  floor: string
  description?: string
  capacity?: number
  status: 'active' | 'inactive' | 'maintenance'
  metadata: Record<string, any>
  createdAt: Date
  updatedAt: Date
}

class MongoDBService {
  private client: MongoClient | null = null
  private db: Db | null = null
  private isConnected = false

  /**
   * 连接数据库
   */
  async connect(): Promise<void> {
    if (this.isConnected && this.client) {
      return
    }

    try {
      this.client = new MongoClient(MONGODB_URI)
      await this.client.connect()
      this.db = this.client.db(DB_NAME)
      this.isConnected = true
      console.log('✅ MongoDB 连接成功')
    } catch (error) {
      console.error('❌ MongoDB 连接失败:', error)
      throw error
    }
  }

  /**
   * 断开数据库连接
   */
  async disconnect(): Promise<void> {
    if (this.client) {
      await this.client.close()
      this.client = null
      this.db = null
      this.isConnected = false
      console.log('🔌 MongoDB 连接已断开')
    }
  }

  /**
   * 确保数据库连接
   */
  private async ensureConnection(): Promise<Db> {
    if (!this.isConnected || !this.db) {
      await this.connect()
    }
    return this.db!
  }

  /**
   * 获取集合
   */
  private async getCollection<T>(name: string): Promise<Collection<T>> {
    const db = await this.ensureConnection()
    return db.collection<T>(name)
  }

  // 医院相关操作
  async addHospital(hospital: Omit<HospitalData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<HospitalData> {
    const collection = await this.getCollection<HospitalData>('hospitals')
    const data: HospitalData = {
      ...hospital,
      id: `hospital_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getHospitals(): Promise<HospitalData[]> {
    const collection = await this.getCollection<HospitalData>('hospitals')
    return await collection.find({}).toArray()
  }

  async getHospital(id: string): Promise<HospitalData | null> {
    const collection = await this.getCollection<HospitalData>('hospitals')
    return await collection.findOne({ id })
  }

  // 科室相关操作
  async addDepartment(department: Omit<DepartmentData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<DepartmentData> {
    const collection = await this.getCollection<DepartmentData>('departments')
    const data: DepartmentData = {
      ...department,
      id: `dept_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getDepartmentsByHospital(hospitalId: string): Promise<DepartmentData[]> {
    const collection = await this.getCollection<DepartmentData>('departments')
    return await collection.find({ hospitalId }).toArray()
  }

  // 设备相关操作
  async addEquipment(equipment: Omit<EquipmentData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<EquipmentData> {
    const collection = await this.getCollection<EquipmentData>('equipment')
    const data: EquipmentData = {
      ...equipment,
      id: `equip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getEquipmentByHospital(hospitalId: string): Promise<EquipmentData[]> {
    const collection = await this.getCollection<EquipmentData>('equipment')
    return await collection.find({ hospitalId }).toArray()
  }

  // 告警相关操作
  async addAlert(alert: Omit<AlertData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<AlertData> {
    const collection = await this.getCollection<AlertData>('alerts')
    const data: AlertData = {
      ...alert,
      id: `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getAlertsByHospital(hospitalId: string): Promise<AlertData[]> {
    const collection = await this.getCollection<AlertData>('alerts')
    return await collection.find({ hospitalId }).toArray()
  }

  // 患者流量相关操作
  async addPatientFlow(patientFlow: Omit<PatientFlowData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<PatientFlowData> {
    const collection = await this.getCollection<PatientFlowData>('patient_flow')
    const data: PatientFlowData = {
      ...patientFlow,
      id: `flow_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getPatientFlowByHospital(hospitalId: string, date?: Date): Promise<PatientFlowData[]> {
    const collection = await this.getCollection<PatientFlowData>('patient_flow')
    const query: any = { hospitalId }
    if (date) {
      const startOfDay = new Date(date)
      startOfDay.setHours(0, 0, 0, 0)
      const endOfDay = new Date(date)
      endOfDay.setHours(23, 59, 59, 999)
      query.date = { $gte: startOfDay, $lte: endOfDay }
    }
    return await collection.find(query).toArray()
  }

  // KPI相关操作
  async addKPI(kpi: Omit<KPIData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<KPIData> {
    const collection = await this.getCollection<KPIData>('kpis')
    const data: KPIData = {
      ...kpi,
      id: `kpi_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getKPIsByHospital(hospitalId: string): Promise<KPIData[]> {
    const collection = await this.getCollection<KPIData>('kpis')
    return await collection.find({ hospitalId }).toArray()
  }

  // POI相关操作
  async addPOI(poi: Omit<POIData, '_id' | 'id' | 'createdAt' | 'updatedAt'>): Promise<POIData> {
    const collection = await this.getCollection<POIData>('pois')
    const data: POIData = {
      ...poi,
      id: `poi_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      updatedAt: new Date()
    }

    const result = await collection.insertOne(data)
    return { ...data, _id: result.insertedId.toString() }
  }

  async getPOIsByHospital(hospitalId: string): Promise<POIData[]> {
    const collection = await this.getCollection<POIData>('pois')
    return await collection.find({ hospitalId }).toArray()
  }

  // 批量操作
  async batchInsert<T>(collectionName: string, documents: T[]): Promise<void> {
    const collection = await this.getCollection<T>(collectionName)
    await collection.insertMany(documents)
  }

  // 清空集合
  async clearCollection(collectionName: string): Promise<void> {
    const collection = await this.getCollection(collectionName)
    await collection.deleteMany({})
  }

  // 创建索引
  async createIndexes(): Promise<void> {
    const db = await this.ensureConnection()

    // 医院索引
    await db.collection('hospitals').createIndex({ id: 1 }, { unique: true })
    await db.collection('hospitals').createIndex({ name: 1 })

    // 科室索引
    await db.collection('departments').createIndex({ id: 1 }, { unique: true })
    await db.collection('departments').createIndex({ hospitalId: 1 })
    await db.collection('departments').createIndex({ type: 1 })

    // 设备索引
    await db.collection('equipment').createIndex({ id: 1 }, { unique: true })
    await db.collection('equipment').createIndex({ hospitalId: 1 })
    await db.collection('equipment').createIndex({ departmentId: 1 })
    await db.collection('equipment').createIndex({ type: 1 })

    // 告警索引
    await db.collection('alerts').createIndex({ id: 1 }, { unique: true })
    await db.collection('alerts').createIndex({ hospitalId: 1 })
    await db.collection('alerts').createIndex({ status: 1 })
    await db.collection('alerts').createIndex({ timestamp: -1 })

    // 患者流量索引
    await db.collection('patient_flow').createIndex({ id: 1 }, { unique: true })
    await db.collection('patient_flow').createIndex({ hospitalId: 1 })
    await db.collection('patient_flow').createIndex({ date: -1 })
    await db.collection('patient_flow').createIndex({ hour: 1 })

    // KPI索引
    await db.collection('kpis').createIndex({ id: 1 }, { unique: true })
    await db.collection('kpis').createIndex({ hospitalId: 1 })
    await db.collection('kpis').createIndex({ metric: 1 })
    await db.collection('kpis').createIndex({ timestamp: -1 })

    // POI索引
    await db.collection('pois').createIndex({ id: 1 }, { unique: true })
    await db.collection('pois').createIndex({ hospitalId: 1 })
    await db.collection('pois').createIndex({ floorId: 1 })
    await db.collection('pois').createIndex({ type: 1 })

    console.log('✅ 数据库索引创建完成')
  }
}

// 创建全局实例
export const mongoDB = new MongoDBService()

export default mongoDB
